/************************************************************
   Copyright 2008 Abhinav Pobbati

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*************************************************************/

#pragma once
#include "Havok4Xna/Physics/Collide/HkpCollide.h"
#include "Havok4Xna/Common/Base/Math/HkVector4.h"
#include "Havok4Xna/Physics/Internal/HkpInternal.h"

#pragma unmanaged
#include <Physics/Collide/Shape/Query/hkpRayHitCollector.h>
#include <Physics/Collide/Shape/hkpShape.h>
#include <Physics/Collide/Shape/Misc/Bv/hkpBvShape.h>
#include <Physics/Collide/Shape/Compound/Tree/hkpBvTreeShape.h>
#include <Physics/Collide/Shape/HeightField/hkpSphereRepShape.h>
#include <Physics/Collide/Shape/Convex/hkpConvexShape.h>
#include <Physics/Collide/Shape/Convex/Capsule/hkpCapsuleShape.h>
#include <Physics/Collide/Shape/Convex/hkpCdVertex.h>
#include <Physics/Collide/Shape/hkpShapeContainer.h>
#include <Physics/Collide/Shape/Compound/Collection/hkpShapeCollection.h>
#include <Physics/Collide/Shape/Compound/Collection/ExtendedMeshShape/hkpExtendedMeshShape.h>
#include <Physics/Collide/Shape/Deprecated/Mesh/hkpMeshShape.h>
#include <Physics/Collide/Shape/Deprecated/FastMesh/hkpFastMeshShape.h>
#include <Physics/Collide/Shape/HeightField/hkpHeightFieldShape.h>
#include <Physics/Collide/Shape/Compound/Collection/List/hkpListShape.h>
#include <Physics/Collide/Shape/Compound/Collection/Mesh/hkpMeshMaterial.h>
#include <Physics/Collide/Shape/Compound/Tree/Mopp/hkpMoppCompilerInput.h>
#include <Physics/Collide/Shape/Compound/Tree/Mopp/hkpMoppUtility.h>
#include <Physics/Collide/Shape/Compound/Tree/Mopp/hkpMoppBvTreeShape.h>
#include <Physics/Collide/Shape/Misc/MultiRay/hkpMultiRayShape.h>
#include <Physics/Collide/Shape/Deprecated/MultiSphere/hkpMultiSphereShape.h>
#include <Physics/Collide/Shape/HeightField/hkpSphereRepShape.h>
#include <Physics/Collide/Shape/Misc/PhantomCallback/hkpPhantomCallbackShape.h>
#include <Physics/Collide/Shape/HeightField/Plane/hkpPlaneShape.h>
#include <Physics/Collide/Shape/Query/hkpRayShapeCollectionFilter.h>
#include <Physics/Collide/Shape/Compound/Tree/Mopp/Modifiers/hkpRemoveTerminalsMoppModifier.h>
#include <Physics/Collide/Shape/HeightField/SampledHeightField/hkpSampledHeightFieldBaseCinfo.h>
#include <Physics/Collide/Shape/HeightField/SampledHeightField/hkpSampledHeightFieldShape.h>
#include <Physics/Collide/Shape/Query/hkpShapeRayCastCollectorOutput.h>
#include <Physics/Collide/Shape/Compound/Collection/SimpleMesh/hkpSimpleMeshShape.h>
#include <Physics/Collide/Shape/Convex/Sphere/hkpSphereShape.h>
#include <Physics/Collide/Shape/Compound/Collection/StorageExtendedMesh/hkpStorageExtendedMeshShape.h>
#include <Physics/Collide/Shape/Deprecated/StorageMesh/hkpStorageMeshShape.h>
#include <Physics/Collide/Shape/HeightField/StorageSampledHeightField/hkpStorageSampledHeightFieldShape.h>
#include <Physics/Collide/Shape/Misc/Transform/hkpTransformShape.h>
#include <Physics/Collide/Shape/Convex/Triangle/hkpTriangleShape.h>
#include <Physics/Collide/Shape/HeightField/TriSampledHeightField/hkpTriSampledHeightFieldBvTreeShape.h>
#include <Physics/Collide/Shape/HeightField/TriSampledHeightField/hkpTriSampledHeightFieldCollection.h>
#pragma managed

namespace Havok4Xna {
	namespace Physics {
		namespace Internal {
			interface class HkpBroadPhaseCastCollector;
			interface class HkpMoppModifier;
		}
	}
}
using Havok4Xna::Physics::Internal::HkpBroadPhaseCastCollector;
using Havok4Xna::Physics::Internal::HkpMoppModifier;

namespace Havok4Xna {
	ref class HkVector4;
	ref class HkAabb;

	namespace Physics {
		namespace Collide {
			ref class HkpShapeRayCastInput;
			ref class HkpShapeRayCastOutput;
			ref class HkpRayHitCollector;
			interface class HkpShapeContainer;

			public enum class HkpShapeType : int {
				Invalid = HK_SHAPE_INVALID,
				Convex = HK_SHAPE_CONVEX,
				FirstShapeType = HK_FIRST_SHAPE_TYPE,
				Sphere = HK_SHAPE_SPHERE,
				Cylinder = HK_SHAPE_CYLINDER,
				Triangle = HK_SHAPE_TRIANGLE,
				Box = HK_SHAPE_BOX,
				Capsule = HK_SHAPE_CAPSULE,
				ConvexVertices = HK_SHAPE_CONVEX_VERTICES,
				Collection = HK_SHAPE_COLLECTION,
				BvTree = HK_SHAPE_BV_TREE,
				List = HK_SHAPE_LIST,
				Mopp = HK_SHAPE_MOPP,
				ConvexTranslate = HK_SHAPE_CONVEX_TRANSLATE,
				ConvexTransform = HK_SHAPE_CONVEX_TRANSFORM,
				SampledHeightField = HK_SHAPE_SAMPLED_HEIGHT_FIELD,
				ExtendedMesh = HK_SHAPE_EXTENDED_MESH,
				UserSPUCollection0 = HK_SHAPE_USER_SPU_COLLECTION_0,
				PackedConvexVertices = HK_SHAPE_PACKED_CONVEX_VERTICES,
				MoppEmbedded = HK_SHAPE_MOPP_EMBEDDED,
				ConvexPiece = HK_SHAPE_CONVEX_PIECE,
				MultiSphere = HK_SHAPE_MULTI_SPHERE,
				ConvexList = HK_SHAPE_CONVEX_LIST,
				TriangleCollection = HK_SHAPE_TRIANGLE_COLLECTION,
				MultiRay = HK_SHAPE_MULTI_RAY,
				HeightField = HK_SHAPE_HEIGHT_FIELD,
				SphereRep = HK_SHAPE_SPHERE_REP,
				Bv = HK_SHAPE_BV,
				Plane = HK_SHAPE_PLANE,
				Transform = HK_SHAPE_TRANSFORM,
				PhantomCallback = HK_SHAPE_PHANTOM_CALLBACK,
				User0 = HK_SHAPE_USER0,
				User1 = HK_SHAPE_USER1,
				User2 = HK_SHAPE_USER2,
				All = HK_SHAPE_ALL
			};

			public interface class HkpShape : public INativeReference {
			/*public:
				void GetAabb(HkTransform ^localToWorld, float tolerance, HkAabb ^outBox);
				float GetMaximumProjection(HkVector4 ^direction);
				bool CastRay(HkpShapeRayCastInput ^input, HkpShapeRayCastOutput ^output);
				void CastRayWithCollector(HkpShapeRayCastInput ^input, HkpCdBody ^cdBody, HkpRayHitCollector ^collector);

				DECLARE_PROPERTY_GETSET(hkUlong, UserData)
				DECLARE_PROPERTY_GET(HkpShapeContainer^, Container)*/
			};

			public interface class HkpShapeContainer : public INativeReference {
				//int GetNumChildShapes();
				//hkpShapeKey GetFirstKey();
				//hkpShapeKey GetNextKey(hkpShapeKey oldKey);
				//hkUint32 GetCollisionFilterInfo(hkpShapeKey key);
				///*HkShape ^GetChildShape(hkpShapeKey key, ShapeBuffer buf);*/
				//bool IsWeldingEnabled();
			};

			public interface class HkpShapeCollection : public HkpShape, public HkpShapeContainer {
				
			};

#define DECLARE_INTERFACE_HkpRayShapeCollectionFilter(type)\
			type bool IsCollisionEnabled(HkpShapeRayCastInput ^aInput, HkpShape ^bShape,\
				HkpShapeContainer ^hContainer, hkpShapeKey bKey);

#define IMPLEMENT_INTERFACE_HkpRayShapeCollectionFilter(implementingClass)\
			bool implementingClass::IsCollisionEnabled(HkpShapeRayCastInput ^aInput, HkpShape ^bShape,\
			HkpShapeContainer ^hContainer, hkpShapeKey bKey) {\
				return _this()->isCollisionEnabled(aInput->_ref(), bShape->_ref(), hContainer->_ref(), bKey);\
			}

			public interface class HkpRayShapeCollectionFilter : public INativeReference {
				DECLARE_INTERFACE_HkpRayShapeCollectionFilter();
			};

			public ref class HkpRayHitCollector : public INativeReference {
			internal:
				HK_CLASS_INTERNALS(HkpRayHitCollector, hkpRayHitCollector)
			};

			public ref class HkpSingleShapeContainer : public HkpShapeContainer {
			internal:
				HK_CLASS_INTERNALS(HkpSingleShapeContainer, hkpSingleShapeContainer)
			};

			public ref class HkpBvShape : public HkpShape {
			internal:
				HK_CLASS_INTERNALS(HkpBvShape, hkpBvShape)
			};

			public ref class HkpBvTreeShape : public HkpShape {
			internal:
				HK_CLASS_INTERNALS(HkpBvTreeShape, hkpBvTreeShape)
			};

			public ref class HkpSphereRepShape : public HkpShape {
			internal:
				HK_CLASS_INTERNALS(HkpSphereRepShape, hkpSphereRepShape)
			};

			public ref class HkpConvexShape : public HkpSphereRepShape {
			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpConvexShape, hkpConvexShape, HkpSphereRepShape)
			};

			public ref class HkpCapsuleShape : public HkpConvexShape {
			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpCapsuleShape, hkpCapsuleShape, HkpConvexShape)
			};

			public ref class HkpCdVertex : public HkVector4 {
			public:
				HkpCdVertex();
				DECLARE_PROPERTY_GET(int, Id)
			};

			public ref class HkpExtendedMeshShape : public HkpShapeCollection {
			public:
				ref class ShapesSubpart : public INativeReference {
				internal:
					HK_CLASS_INTERNALS(ShapesSubpart, hkpExtendedMeshShape::ShapesSubpart)
				};
				ref class TriangleSubpart : public INativeReference {
				internal:
					HK_CLASS_INTERNALS(TriangleSubpart, hkpExtendedMeshShape::TrianglesSubpart)
				};

			internal:
				HK_CLASS_INTERNALS(HkpExtendedMeshShape, hkpExtendedMeshShape)
			};

			ATTR_DEPRECATED
			public ref class HkpMeshShape : public HkpShapeCollection {
			public:
				ref class Subpart : public INativeReference {
				internal:
					HK_CLASS_INTERNALS(Subpart, hkpMeshShape::Subpart)
				};
				
			internal:
				HK_CLASS_INTERNALS(HkpMeshShape, hkpMeshShape)
			};

			ATTR_DEPRECATED
			public ref class HkpFastMeshShape : public HkpMeshShape {
			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpFastMeshShape, hkpFastMeshShape, HkpMeshShape)
			};

			public ref class HkpSimpleMeshShape : public HkpShapeCollection {
			internal:
				HK_CLASS_INTERNALS(HkpSimpleMeshShape, hkpSimpleMeshShape)
			};

			public ref class HkpHeightFieldShape : public HkpShape {
			internal:
				HK_CLASS_INTERNALS(HkpHeightFieldShape, hkpHeightFieldShape)
			};

			public ref class HkpListShape : public HkpShapeCollection {
			internal:
				HK_CLASS_INTERNALS(HkpListShape, hkpListShape)
			};

			public ref class HkpMeshMaterial : public INativeReference {
			internal:
				HK_CLASS_INTERNALS(HkpMeshMaterial, hkpMeshMaterial)
			};

			public ref class HkpMoppCompilerInput : public INativeReference {
			internal:
				HK_CLASS_INTERNALS(HkpMoppCompilerInput, hkpMoppCompilerInput)
			};

			public ref class HkpMoppUtility : public INativeReference {
			internal:
				HK_CLASS_INTERNALS(HkpMoppUtility, hkpMoppUtility)
			};

			public ref class HkpMoppBvTreeShape : public INativeReference {
			internal:
				HK_CLASS_INTERNALS(HkpMoppBvTreeShape, hkpMoppBvTreeShape)
			};

			public ref class HkpMultiRayShape : public HkpShape {
			public:
				ref class Ray : public INativeReference {
				internal:
					HK_CLASS_INTERNALS(Ray, hkpMultiRayShape::Ray)
				};
			
			internal:
				HK_CLASS_INTERNALS(HkpMultiRayShape, hkpMultiRayShape)
			};

			ATTR_DEPRECATED
			public ref class HkpMultiSphereShape : public HkpSphereRepShape {
			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpMultiSphereShape, hkpMultiSphereShape, HkpSphereRepShape)
			};

			public ref class HkpSphereShape : public HkpConvexShape {
			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpSphereShape, hkpSphereShape, HkpConvexShape)
			};

			public ref class HkpPhantomCallbackShape : public HkpShape {
			internal:
				HK_CLASS_INTERNALS(HkpPhantomCallbackShape, hkpPhantomCallbackShape)
			};

			public ref class HkpPlaneShape : public HkpHeightFieldShape {
			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpPlaneShape, hkpPlaneShape, HkpHeightFieldShape)
			};

			public ref class HkpRemoveTerminalsMoppModifier : public HkpMoppModifier {
			internal:
				HK_CLASS_INTERNALS(HkpRemoveTerminalsMoppModifier, hkpRemoveTerminalsMoppModifier)
			};

			public ref class HkpSampledHeightFieldBaseCinfo : public INativeReference {
			internal:
				HK_CLASS_INTERNALS(HkpSampledHeightFieldBaseCinfo, hkpSampledHeightFieldBaseCinfo)
			};

			public ref class HkpSampledHeightFieldShape : public HkpHeightFieldShape {
			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpSampledHeightFieldShape, hkpSampledHeightFieldShape, HkpHeightFieldShape)
			};

			public ref class HkpShapeRayCastCollectorOutput : public INativeReference {
			internal:
				HK_CLASS_INTERNALS(HkpShapeRayCastCollectorOutput, hkpShapeRayCastCollectorOutput)
			};

			public ref class HkpShapeRayCastOutput : public HkpShapeRayCastCollectorOutput {
			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpShapeRayCastOutput, hkpShapeRayCastOutput, HkpShapeRayCastCollectorOutput)
			};

			public ref class HkpStorageExtendedMeshShape : public HkpExtendedMeshShape {
			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpStorageExtendedMeshShape, hkpStorageExtendedMeshShape, HkpExtendedMeshShape)
			};

			ATTR_DEPRECATED
			public ref class HkpStorageMeshShape : public HkpMeshShape {
			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpStorageMeshShape, hkpStorageMeshShape, HkpMeshShape)
			};

			public ref class HkpStorageSampledHeightFieldShape: public HkpSampledHeightFieldShape {
			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpStorageSampledHeightFieldShape, hkpStorageSampledHeightFieldShape, HkpSampledHeightFieldShape)
			};

			public ref class HkpTransformShape : public HkpShape {
			internal:
				HK_CLASS_INTERNALS(HkpTransformShape, hkpTransformShape)
			};

			public ref class HkpTriangleShape : public HkpConvexShape {
			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpTriangleShape, hkpTriangleShape, HkpConvexShape)
			};
			
			public ref class HkpTriSampledHeightFieldBvTreeShape : public HkpBvTreeShape {
			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpTriSampledHeightFieldBvTreeShape, hkpTriSampledHeightFieldBvTreeShape, HkpBvTreeShape)
			};

			public ref class HkpTriSampledHeightFieldCollection : public HkpShapeContainer {
			internal:
				HK_CLASS_INTERNALS(HkpTriSampledHeightFieldCollection, hkpTriSampledHeightFieldCollection)
			};
		}
	}
}
